package com.atguigu.gulimall.product.web;

import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;

import com.atguigu.gulimall.product.vo.Catelog2Vo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author ming
 * @create 2022/4/28
 * @description:
 */
@Controller
public class IndexController {
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private RedissonClient redisson;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @GetMapping({"/","/index.html"})
    public String indexPage(Model model){
        //查出所有的一级分类
        List<CategoryEntity> categories = categoryService.getLevel1Category();
        model.addAttribute("categories",categories);
        return "index";
    }
    @GetMapping("/index/json/catalog.json")
    @ResponseBody
    public Map<String, List<Catelog2Vo>> getCatalogJson(){
        Map<String, List<Catelog2Vo>> map  = categoryService.getCatalogJson();
        return map;
    }
    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        //读+读相当于无锁  并发读,只会在redis中记录所有当前的读锁,他们同时加锁成功
        //读＋写 阻塞模式 (有读锁,写也需要等待,只要有写都得等待所有的锁释放
        RLock lock = redisson.getLock("my-lock");
        //  lock.lock(10, TimeUnit.SECONDS);不会续期
        //如果我们传递了锁的超时时间默认就是我们制定的时间
        //如果没有指定超时时间,就会启动一个定时任务
        //lock.lock(10, TimeUnit.SECONDS);
        lock.lock(); //无限等待阻塞等待
        //最佳实战 lock.lock(10, TimeUnit.SECONDS); 指定时间解锁
        System.out.println("加锁成功,执行业务"+Thread.currentThread().getId());
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{
            System.out.println("释放锁"+Thread.currentThread().getId());
            lock.unlock();
        }
        return "hello";


    }
    @ResponseBody
    @GetMapping("/write")
    public String writeValue(){
        String uuid = UUID.randomUUID().toString();
        RReadWriteLock lock = redisson.getReadWriteLock("rw-loc");
        RLock rLock = lock.writeLock();
        try {
            //该数据加写锁,读数据加读锁
           //读写锁一定能读到最新的数据,修改期间是一个排它锁只能有一个写锁,读锁是共享锁
            //写+读
            //写+写 阻塞方式
            //读+写
            rLock.lock();
            Thread.sleep(30000);
            System.out.println("获取写锁成功");
            redisTemplate.opsForValue().set("wirteValue",uuid);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            System.out.println("写锁释放成功");
            rLock.unlock();
        }
        return uuid;
    }
    @ResponseBody
    @GetMapping("/read")
    public String readValue(){
        RReadWriteLock lock = redisson.getReadWriteLock("rw-loc");
        RLock rLock = lock.readLock();
        rLock.lock();
        String s="";
        try {
           s = redisTemplate.opsForValue().get("wirteValue");
            System.out.println("读获得取锁");
           Thread.sleep(30000);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("读取解锁成功");
            rLock.unlock();
        }

        return s ;
    }
    /**
     *
     *
     */
    @GetMapping("/lockDoor")
    @ResponseBody
    public String lockDoor(){
        RCountDownLatch door = redisson.getCountDownLatch("door");
        try {
            door.trySetCount(5);
            door.await();//等待闭锁都完成
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "放假了";
    }
    @GetMapping("/gogo/{id}")
    public String gogo(@PathVariable("id")  Long id){
        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.countDown();//计数减一
        return id+"班的人都走了";
    }
    @GetMapping("/park")
    @ResponseBody
    public String park() throws InterruptedException {
        RSemaphore park = redisson.getSemaphore("park");
        //park.acquire(); //获取一个信号
        boolean b = park.tryAcquire();
        return "ok=="+b ;
    }
    @GetMapping("/go")
    @ResponseBody
    public String go() throws InterruptedException {
        RSemaphore park = redisson.getSemaphore("park");
        park.release(); //获取一个信号
        
        return "ok";
    }
    
}
